package fr.bludwarf.skywarrior.stats;

import org.apache.commons.configuration.ConfigurationException;

import fr.bludwarf.skywarrior.exceptions.IleInconnueException;
import fr.bludwarf.skywarrior.exceptions.JoueurInconnuException;
import fr.bludwarf.skywarrior.global.EtatMonde;
import fr.bludwarf.skywarrior.global.Partie;
import fr.bludwarf.skywarrior.global.Properties;
import fr.bludwarf.skywarrior.global.Temps;
import fr.bludwarf.skywarrior.ile.Construction;
import fr.bludwarf.skywarrior.ile.EtatIle;
import fr.bludwarf.skywarrior.ile.Ile;
import fr.bludwarf.skywarrior.joueur.Joueur;
import fr.bludwarf.skywarrior.joueur.Ressources;
import fr.bludwarf.skywarrior.joueur.Unite;

public class Prevision<U extends Unite>
{
	
	private EtatMonde _etatFinal;
//	private EtatMonde _etatMondeInit;
	private U _unite;
	private Ile _ile;
	private Partie _partie;
	private boolean _lancee;
	private double _dureeStabilisation;
	private int _n;
	private Construction _constructionType;

	public Prevision(Partie partie, U unite) throws Exception
	{
//		_etatMonde = etatMonde.cloneFor(getClass());
//		_etatMondeInit = etatMonde;
		_partie = partie;
		_unite = unite;
	}

	public Prevision(Partie partie, U unite, Ile ile) throws Exception
	{
		this(partie, unite);
		_ile = ile;
	}
	
	/**
	 * On continue d'avancer tant que le temps de construction de l'unité ne s'est pas stabilisé
	 * @throws ConfigurationException 
	 * @throws JoueurInconnuException 
	 * @throws IleInconnueException 
	 */
	private void lancer() throws Exception
	{		
		// Vars
		double dureePrecedent = 0;
		double delta = Temps.INFINI;
		double dureeStabilisation = 0;
		int n = 0;
		int nMax = Properties.getInstance().getInt("Prevision.nMax");
		
		while (n < nMax && Math.round(delta) != 0)
		{
			final Temps temps = _partie.getTemps();
			
			// TODO : mode sans affichage car simulation
			_partie.construire(_unite);
			_partie.avancer();
			
			final double duree = _partie.getTemps().tempsEcouleDepuis(temps);
			delta = duree - dureePrecedent;
			dureeStabilisation += duree;
			dureePrecedent = duree;
			++n;
		}
		
		_lancee = true;
		_dureeStabilisation = dureeStabilisation;
		_n = n;
		_etatFinal = _partie.getEtat();
		_constructionType = _etatFinal.getConstructions().get(_etatFinal.getConstructions().size() - 1);
	}
	
	public Ile getIle() throws JoueurInconnuException
	{
		if (_ile == null)
		{
			final Joueur joueur = _partie.getJoueurPrincipal();
			_ile = joueur.getIlePrincipale();
		}
		return _ile;
	}
	
	@Override
		public String toString()
		{
			try
			{
				if (!_lancee)
				{
					lancer();
				}
				
				// TODO : utiliser des getters
				final Ressources cout = _constructionType.getCoutParCycle();
				Ressources prod = _partie.getProduction();
				prod.remove(cout);
				
				return String.format("Prévision de production de %3$ss sur %7$s après %2$s (n=%1$s)\t: m=%4$+04d e=%5$+04d t=%6$s",
					_n,
					Temps.formatDuree(_dureeStabilisation),
					_unite.getNom(),
					prod.materiaux(),
					prod.ether(),
					Temps.formatDuree(_constructionType.getDureeReelle()),
					_etatFinal.getJoueurPrincipal().getIlePrincipale().getNom()
					);
				
			}
			catch (Exception e)
			{
				e.printStackTrace();
				return "ERR";
			}
		}

}
